(() => {
  // --------------------- 1. 数字枚举 ---------------------
  enum Color {
    Red,
    Green,
    Blue
  }

  /**
   * 等同于
   * enum Color {
   *   Red = 0,
   *   Green = 1,
   *   Blue = 2
   * }
   * 默认从零开始，可以手动指定初始索引值
   */

  // --------------------- 2. 增长枚举 ---------------------
  enum Color1 {
    Red = 1,
    Green,
    Blue
  }

  /**
   * 等同于
   * enum Color1 {
   *   Red = 1,
   *   Green = 2,
   *   Blue = 3
   * }
   * 默认从零开始，可以手动指定初始索引值
   */

  // --------------------- 3. 字符串枚举 ---------------------
  enum Color2 {
    Red = "red",
    Green = "green",
    Blue = "blue"
  }

  // --------------------- 4. 异构枚举 ---------------------
  /**
   * 异构枚举
   * 数字枚举和字符串枚举可以混用
   */
  enum Type {
    No = 'No',
    Yes = 1
  }

  // --------------------- 5. 接口枚举 ---------------------
  enum Type1 {
    yyds = 'yyds',
    dddd = 'dddd'
  }
  interface A {
    red: Type1.yyds
  }
  let obj: A = {
    red: Type1.yyds
  }
  console.log(obj.red);  // yyds

  // --------------------- 6. const枚举 ---------------------
  /**
   * const枚举
   * 1. 常量枚举，编译阶段会被完全移除
   * 2. let  和 var 都是不允许的声明只能使用const
   * 3. const 声明的枚举会被编译成常量,普通声明的枚举编译完后是个对象
   */
  const enum Color3 {
    Red = 'red',
    Green = 'green',
    Blue = 'blue'
  }
  console.log(Color3.Red);
  console.log(Color3.Green);
  console.log(Color3.Blue);

  // 编译后
  // console.log("red" /* Color3.Red */);
  // console.log("green" /* Color3.Green */);
  // console.log("blue" /* Color3.Blue */);

  enum Color4 {
    Red = 'red',
    Green = 'green',
    Blue = 'blue'
  }
  console.log(Color4.Red);
  console.log(Color4.Green);
  console.log(Color4.Blue);

  // 编译后
  // var Color4;
  // (function (Color4) {
  //     Color4["Red"] = "red";
  //     Color4["Green"] = "green";
  //     Color4["Blue"] = "blue";
  // })(Color4 || (Color4 = {}));
  // console.log(Color4.Red);
  // console.log(Color4.Green);
  // console.log(Color4.Blue);

  // --------------------- 7. 反向映射 ---------------------
  /**
   * 反向映射
   * 1. 枚举值可以反向映射到枚举名
   * 2. 原理：通过获取枚举内的索引反向获取枚举值
   * 3. 注意：不能使用const声明的枚举去反向映射，因为其底层逻辑是一个对象，无键值对
   */
  enum Enum {
    fall
  }
  let e = Enum.fall  // 0
  let nameOfA = Enum[e]  // "fall"
})()



